import {useEffect, useState} from 'react';
import {useUpdate} from './useUpdate';
import {Category, CategoryMap, useTags} from 'hooks/useTags';
import day from 'dayjs';
import {createId} from 'lib/createId';
import _ from 'lodash';
import fakeRecords from 'fakeRecords.json';
import {generateCurrentFakeRecords} from '../lib/generateCurrentFakeRecords';
import {toFixedFloat} from '../lib/toFixedFloat';

type RecordItem = {
  tagId: number;
  notes: string;
  amount: number;
  createdAt: string;
}

export type RecordItemWithId = {
  category: Category;
  id: number;
} & RecordItem

export type MonthRecords = {
  [K: string]: { dateCost: number, dateIncome: number, subRecords: RecordItemWithId[] }
}

const useRecords = () => {
  const [records, setRecords] = useState<RecordItemWithId[]>([]);
  const {tags, findTag} = useTags();

  useEffect(() => {
    let localRecords = JSON.parse(window.localStorage.getItem('records') || '[]');
    if (localRecords.length === 0) {
      localRecords = generateCurrentFakeRecords(fakeRecords);
      window.localStorage.setItem('records', JSON.stringify(records));
    }
    setRecords(localRecords);
  }, []);

  useUpdate(() => {
    window.localStorage.setItem('records', JSON.stringify(records));
  }, [records]);

  const addRecord = (newRecord: RecordItem) => {
    const newRecordWithId = {
      id: createId('maxRecordId'),
      category: findTag(newRecord.tagId)?.category,
      ...newRecord
    };
    setRecords([...records, newRecordWithId]);
    return true;
  };


  const findRecord = (id: number) => records.filter(record => record.id === id)[0];
  const findRecordsByTagId = (tagId: number) => records.filter(record => record.tagId === tagId);

  const deleteRecord = (id: number) => setRecords(records.filter(record => record.id !== id));

  const moveRecordsByTagId = (prevTagId: number) => {
    const category = findTag(prevTagId).category
    const tagId = (tags.filter(tag=>tag.name === `其它${CategoryMap[category]}`)[0]).id
    setRecords(records.map(record => record.tagId === prevTagId ? {...record, tagId} : record));
  }

  const updateRecord = (id: number, obj: { notes: string, amount: number, createdAt: string }) => {
    setRecords(records.map(record => record.id === id ? {...record, ...obj} : record));
  };

  /***
   * 计算单日的收入与支出
   * 参数：
   *  currentDate: 当前日期
   * 返回值：
   *  dateCost: 单日支出
   *  dateIncome: 单日收入
   *  subRecords: 单日账目明细，包含每一条账目记录
   * ***/
  const calculateDateTotal = (currentDate: string) => {
    const subRecords = _.filter(records, {'createdAt': currentDate});
    let dateCost = subRecords.reduce(
      (accumulator, item) => item.category === '-' ? accumulator + item.amount : accumulator, 0);
    let dateIncome = subRecords.reduce(
      (accumulator, item) => item.category === '+' ? accumulator + item.amount : accumulator, 0);
    dateCost = toFixedFloat(dateCost)
    dateIncome = toFixedFloat(dateIncome)
    return {dateCost, dateIncome, subRecords};
  };

  /***
   * 计算当月的收入与支出
   * 参数：
   *  currentDate: 当前日期
   * 返回值：
   *  monthCost: 当月支出
   *  monthIncome: 当月收入
   *  monthRecords: 当月账目明细，包含每天的总收入，总支出及每条账目明细
   * ***/
  const calculateMonthTotal = (currentDate: string) => {
    const monthStart = day(currentDate).startOf('month');
    const monthEndNumber = day(currentDate).endOf('month').date();
    let monthCost = 0;
    let monthIncome = 0;
    let monthRecords: MonthRecords = {};
    for (let i = 0; i < monthEndNumber; i++) {
      const tempDate = day(monthStart).add(i, 'day').format('YYYY-MM-DD');
      const {dateCost, dateIncome, subRecords} = calculateDateTotal(tempDate);
      if (dateCost !== 0 || dateIncome !== 0) {
        monthRecords[tempDate] = {dateCost, dateIncome, subRecords};
      }
      monthCost += dateCost;
      monthIncome += dateIncome;
    }
    monthCost = toFixedFloat(monthCost)
    monthIncome = toFixedFloat(monthIncome)
    return {monthCost, monthIncome, monthRecords};
  };

  /***
   * 计算前六个月的月收入，月支出及月结余
   * 参数：
   *  currentDate: 当前日期
   * 返回值：
   *  data: 用作ECharts柱状及折线图的dataset
   * ***/
  const generateTrends = (currentDate: string) => {
    let data = [['年月', '支出', '收入', '结余']] as (string[] | [string, number, number, number])[];
    for (let i = 5; i >= 0; i--) {
      const month = day(currentDate).subtract(i, 'month');
      const label = month.format('YYYY.MM');
      const {monthCost, monthIncome} = calculateMonthTotal(month.format());
      data.push([label, monthCost, monthIncome, toFixedFloat(monthIncome - monthCost)]);
    }
    return data;
  };

  /***
   * 计算当月账目中各类别所占比例
   * 参数：
   *  currentDate: 当前日期
   * 返回值：
   *  source: 用作ECharts饼图的dataset
   * ***/
  const generateTagsMonthTable = (currentDate: string) => {
    const subRecords = _.filter(records, (record) => record.createdAt.substring(0, 8) === currentDate.substring(0, 8));
    const calculateTagTotal = (tagId: number) => {
      return _.filter(subRecords, {tagId}).reduce((accumulator, item) => accumulator + item.amount, 0);
    };
    const title = [['tagName', 'category', 'amount']] as (string[] | [string, Category, number])[];
    const source = title.concat(
      tags.map((tag) => [tag.name, tag.category, calculateTagTotal(tag.id)])
    );
    return source;
  };

  return {
    records, addRecord, findRecord, findRecordsByTagId, deleteRecord, moveRecordsByTagId, updateRecord,
    calculateDateTotal, calculateMonthTotal, generateTrends, generateTagsMonthTable,
  };
};

export {useRecords};